memo
函式用於建立一個在其父層重新渲染時不會重新渲染的元件,只要該元件在渲染之間 props 保持不變,但是當元件本身的狀態或是訂閱的 context 發生變化時,memo 元件仍然會重新渲染,因此,要特別提醒只有 props 會影響。
讓我們先將一般元件 Archive
放入 memo
函式裡面,將其包裝成 memo
元件。
// 一般元件
function Archive({ show }) {
...
}
// memo 元件
const Archive = memo(function Archive({ show }) {
...
});
接著來看一個例子,當我們點擊 button 按鈕更新 count 的狀態,App
元件會重新渲染,接著其子元件 Archive
也會重新渲染,但此時的 Archive
已經是一個 memo
元件,並且在渲染之間它的 props 始終保持 true
,因此,即使父層 App
重新渲染,Archive
也不會重新渲染。
import { useState, memo } from "react";
function App() {
const [count, setCount] = useState(0);
return (
<section>
<h2>{count}</h2>
<button onClick={() => setCount((count) => count + 1)}>++</button>
<Archive show={true} />
</section>
);
}
const Archive = memo(function Archive({ show }) {
console.log("Archive");
return <h1>Archive</h1>;
});
但是當我們傳入的 props 是一個物件的時候,還是會導致重新渲染,這是為什麼呢?
原因是因為每當 App
重新渲染的時候,archiveOptions
這個物件會被重新建立,此時 archiveOptions
已經不是原本的那個物件,因此,archiveOptions
被視為一個新的 props 傳入,Archive
自然也就會重新渲染了,那該如何解決這個問題點呢?我們將在明天的文章裡介紹。
import { useState, memo } from "react";
function App() {
const [count, setCount] = useState(0);
const archiveOptions = {
show: false,
title: "Post archive"
};
return (
<section>
<h2>{count}</h2>
<button onClick={() => setCount((count) => count + 1)}>++</button>
<Archive archiveOptions={archiveOptions} />
</section>
);
}
const Archive = memo(function Archive({ show, title }) {
console.log(show);
return <h1>{title}</h1>;
});
{} !== {}
)。memo
將不起作用。memoized {} == memoized {}
)。透過 memo
函式,我們可以建立一個當父層重新渲染時不會重新渲染的元件,只要該元件的 props 在渲染之間保持不變,當父層會頻繁觸發重新渲染的時候,就可以將元件包裝成 memo
元件來避免不必要的重新渲染。